const Service = require('egg').Service;
const path = require('path');
const FolderScanner = require('@moyufed/folder-scanner');

class UploadService extends Service {
    /**
     * 将文件夹里面的文件上传到CDN，通用方法
     *
     * @param {*} location 需要扫描的文件夹，一般是具体目录ID所在的版本路径
     * @param {*} dir 目录ID
     * @param {*} prefix 需要上传的CDN地址目录前缀
     * @return {*} 
     * @memberof UploadService
     */
    async uploadQiniu(location, dir, prefix) {
        const ctx = this.ctx;
        this.uploadPool = [];
        this._createUpload(); // 创建上传池
        console.log(location, dir);
        this._getUpload();
        // kodo://bucket1/exe-cdn/test/
        const folderScanner = new FolderScanner({
            location: location,
            rootFolder: dir
        });
        const files = JSON.parse(folderScanner.getFiles().replace(',]', ']'))
        this.files = files.map(file => {
            return {
                key: file,
                status: 0,
                path: prefix ? prefix + file.replace('/' + dir, '') : 'exe-cdn/test' + file,
                location: path.join(location, file)
            }
        });
        // 单个上传
        // if (files && files.length) {
        //     for (let file of files) {
        //         console.log(file);
        //         const fileDir = path.join(location, file);
        //         console.log(fileDir);
        //         const result = await ctx.app.fullQiniu.get('exe').uploadFile('exe-cdn/test' + file, fileDir);
        //     }
        // }

        // 批量上传
        await this.doUpload(this.files);

        return true;
    }

    async replaceAuthPage(cdn) {
        const ctx = this.ctx;
        const bucket = ctx.app.fullQiniu.get('exe');
        if (cdn.type === 4) {
            await this._copyDdPage(cdn, bucket, 'dingtalkauth.html');
            if(cdn.tenantId === 'common') {
                await this._copyDdPage(cdn, bucket, 'dingtalkisvauth.html');
            }
            const bucket2 = ctx.app.fullQiniu.get('html');
            const prefix = cdn.authPage.replace('https://mobile.exexm.com/', '');
            await this._replaceAuthPage(cdn, bucket2, prefix)
        } else {
            const prefix = cdn.authPage.replace('https://res.exexm.com/', '');
            await this._replaceAuthPage(cdn, bucket, prefix)
        }
    }

    async _replaceAuthPage(cdn, bucket, prefix) {
        const ctx = this.ctx;
        const fileName = cdn.authPage.replace(/[\s\S]*\//g, '');
        const fileDir = path.resolve(process.cwd(), 'upload', 'auth', ctx.app.config.envType[cdn.env], ctx.app.config.tenantType[cdn.type], 'new');
        let item;
        const result = await bucket.listPrefix({
            prefix
        });
        if (result.ok) {
            item = result.items[0];
        } else {
            throw new Error('获取鉴权页失败，请重试！');
        }
        const deleteResult = await bucket.delete(item.key);
        if (deleteResult.ok) {
            const pathName = path.resolve(fileDir, fileName);
            const newResult = await bucket.uploadFile(item.key, pathName);
            if (newResult.ok) {
                await ctx.service.version.removeVersionStatus(cdn._id)
                await ctx.service.version.updateVersion({ _id: cdn.newVersion._id }, { status: 1 })
                return true
            } else {
                throw new Error('警告，替换文件失败，旧的中间页已经被删除，请恢复！');
            }
        } else {
            throw new Error('替换文件失败！');
        }
    }

    async _copyDdPage(cdn, bucket, fileName) {
        const authPage = cdn.resource.replace('{version}/' + cdn.tenantId, 'auth_backup') + '/' + fileName;
        const newPage = cdn.resource.replace('{version}/' + cdn.tenantId, cdn.newVersion.version) + '/' + fileName;
        const authPageInfo = await bucket.listPrefix({
            prefix: authPage
        });
        if (authPageInfo.ok && authPageInfo.items.length > 0) {
            const resultItem = authPageInfo.items[0];
            const copyResult = await bucket.copy(resultItem.key, 'bucket1', newPage, true);
            return copyResult.ok;
        } else {
            throw new Error('缺少旧的版本中间页，版本为：' + cdn.version)
        }
    }

    _createUpload() {
        const ctx = this.ctx;
        for (let i = 0; i < 10; i++) {
            this.uploadPool[i] = {
                instance: ctx.app.fullQiniu.get('exe'),
                free: true
            }
        }
    }

    _getUpload() {
        let upload;
        if (this.uploadPool.length) {
            for (let item of this.uploadPool) {
                if (item && item.free) {
                    item.free = false;
                    upload = item;
                    break
                }
            }
        }
        return upload;
    }

    doUpload(files) {
        return new Promise((resolve, reject) => {
            let count = 0;
            let fileUploaded = 0;
            let errorFiles = [];
            const _this = this;
            const _complete = () => {
                if (files && files.length === 0 && count === 0) {
                    console.log('complete');
                    console.log('错误文件列表：', errorFiles);
                    if (errorFiles.length > 0) {
                        console.log(errorFiles);
                        reject(errorFiles);
                    }
                    resolve(true);
                }
                if (files && files.length) {
                    _upload();
                }
            }
            function _upload() {
                const upload = _this._getUpload();
                if (upload) {
                    const f = files.pop();
                    count++;
                    // if (fileUploaded && fileUploaded % 10 === 0) {
                    //     console.log(fileUploaded);
                    //     f.location = f.location + '.a'
                    // }
                    upload.instance.uploadFile(f.path, f.location).then(res => {
                        // console.log('complete ' + f.location);
                        upload.free = true;
                        count--;
                        if (res.ok) {
                            fileUploaded++;
                        } else {
                            console.log(res.err.toString());
                            // f.error = res.err;
                            // errorFiles.push(f);
                        }
                        _complete();
                    }).catch(err => {
                        f.error = err;
                        errorFiles.push(f);
                        upload.free = true;
                        count--;
                        _complete();
                    })
                    if (files && files.length) {
                        _upload();
                    }
                }
            }
            if (files && files.length) {
                _upload()
            }
        })
    }
}

module.exports = UploadService;